﻿#region Copyright and License Notice
// Copyright (C)2010-2016 - Rob Levine and other contributors
// http://configgen.codeplex.com
// 
// This file is part of ConfigGen.
// 
// ConfigGen is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// ConfigGen is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License and 
// the GNU Lesser General Public License along with ConfigGen.  
// If not, see <http://www.gnu.org/licenses/>
#endregion

using System.Linq;
using System.Reflection;
using ConfigGen.Core.SettingsLoader;
using ConfigGen.Utilities.Extensions.System.Reflection;
using Microsoft.Practices.Unity;
using NUnit.Framework;

namespace ConfigGen.Core.Tests.SettingsLoader
{
    [TestFixture]
    public class ExcelSettingsLoaderEndToEndTests
    {        
        [Test]
        public void LoadSettings002_ServerLevelInfo()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (var testFile = Assembly.GetExecutingAssembly().GetEmbeddedResourceFile("SettingsLoader.SampleFiles.App.Config.Settings.xlsx", "App.Config.Settings.xlsx"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);

                Assert.IsNotNull(settingsCollection, "settingsCollection should not have been null");
                Assert.IsTrue(settingsCollection.MachineConfigurationSettings.Any(), "settingsCollection should not have been empty");

                var settings = settingsCollection.MachineConfigurationSettings.ToList();
                Assert.AreEqual("DevServer", settings[0].MachineName, "Incorrect MachineName 0");
                Assert.AreEqual("DevServer\\App.Config", settings[0].ConfigFilePath, "Incorrect ConfigFilePath 0");

                Assert.AreEqual("UatServer", settings[1].MachineName, "Incorrect MachineName 1");
                Assert.AreEqual("UatServer\\App.Config", settings[1].ConfigFilePath, "Incorrect ConfigFilePath 1");

                Assert.AreEqual("ProdServer", settings[2].MachineName, "Incorrect MachineName 2");
                Assert.AreEqual("ProdServer\\App.Config", settings[2].ConfigFilePath, "Incorrect ConfigFilePath 2");

                Assert.AreEqual("MyWorkstation", settings[3].MachineName, "Incorrect MachineName 3");
                Assert.AreEqual("MyWorkstation\\App.Config", settings[3].ConfigFilePath, "Incorrect ConfigFilePath 3");

                Assert.AreEqual("Default", settings[4].MachineName, "Incorrect MachineName 4");
                Assert.AreEqual("Default\\App.Config", settings[4].ConfigFilePath, "Incorrect ConfigFilePath 4");
            }
        }

        [Test]
        public void LoadSettings003_Values()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (var testFile = Assembly.GetExecutingAssembly().GetEmbeddedResourceFile("SettingsLoader.SampleFiles.App.Config.Settings.xlsx", "App.Config.Settings.xlsx"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);
                const string settingStub = "Setting";

                foreach (var settings in settingsCollection.MachineConfigurationSettings)
                {
                    var machineName = settings.MachineName;

                    for (var i = 1; i <= 5; i++)
                    {
                        var setting = settingStub + i;
                        Assert.IsTrue(settings.Contains(setting), setting + " not found for " + machineName);
                        var settingValue = string.Format("{0}_Setting{1}", machineName, i);
                        Assert.AreEqual(settingValue, settings[setting].Value, "Incorrect " + setting + " for " + machineName);
                    }

                }
            }
        }

        /// <summary>
        /// Asserts that if a row has a missing machine name entry, the line is ignored.
        /// Regression test: http://configgen.codeplex.com/workitem/11
        /// </summary>
        [Test]
        public void LoadSettings004_BlankMachineNameInRow()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (
                var testFile =
                    Assembly.GetExecutingAssembly().GetEmbeddedResourceFile(
                        "SettingsLoader.SampleFiles.BlankMachineName.App.Config.Settings.xlsx",
                        "BlankMachineName.App.Config.Settings.xlsx"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);

                Assert.IsNotNull(settingsCollection, "settingsCollection should not have been null");
                Assert.AreEqual(1, settingsCollection.MachineConfigurationSettings.Count(), "settingsCollection should contain one item");
            }
        }

        /// <summary>
        /// Asserts that if a row has a missing config file entry, the line is ignored
        /// Regression test: http://configgen.codeplex.com/workitem/11
        /// </summary>
        [Test]
        public void LoadSettings005_BlankConfigFileInRow()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (
                var testFile =
                    Assembly.GetExecutingAssembly().GetEmbeddedResourceFile(
                        "SettingsLoader.SampleFiles.BlankConfigFile.App.Config.Settings.xlsx",
                        "BlankConfigFile.App.Config.Settings.xlsx"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);

                Assert.IsNotNull(settingsCollection, "settingsCollection should not have been null");
                Assert.AreEqual(1, settingsCollection.MachineConfigurationSettings.Count(), "settingsCollection should contain one item");
            }
        }

        /// <summary>
        /// Asserts that if a row contains only whitespace for the machine name entry, the line is ignored
        /// Regression test: http://configgen.codeplex.com/workitem/11
        /// </summary>
        [Test]
        public void LoadSettings006_WhitespaceOnlyMachineNameInRow()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (
                var testFile =
                    Assembly.GetExecutingAssembly().GetEmbeddedResourceFile(
                        "SettingsLoader.SampleFiles.WhitespaceMachineName.App.Config.Settings.xlsx",
                        "WhitespaceMachineName.App.Config.Settings.xlsx"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);

                Assert.IsNotNull(settingsCollection, "settingsCollection should not have been null");
            }
        }

        /// <summary>
        /// Asserts that if a row contains only whitespace for the config file entry, the line is ignored
        /// Regression test: http://configgen.codeplex.com/workitem/11
        /// </summary>
        [Test]
        public void LoadSettings007_WhitespaceOnlyConfigFileInRow()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (
                var testFile =
                    Assembly.GetExecutingAssembly().GetEmbeddedResourceFile(
                        "SettingsLoader.SampleFiles.WhitespaceMachineName.App.Config.Settings.xlsx",
                        "WhitespaceMachineName.App.Config.Settings.xlsx"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);

                Assert.IsNotNull(settingsCollection, "settingsCollection should not have been null");
                Assert.AreEqual(1, settingsCollection.MachineConfigurationSettings.Count(), "settingsCollection should contain one item");
            }
        }

        /// <summary>
        /// 
        /// </summary>
        [Test]
        public void LoadSettings008_WhitespaceTrimmedFromMachineName()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (
                var testFile =
                    Assembly.GetExecutingAssembly().GetEmbeddedResourceFile(
                        "SettingsLoader.SampleFiles.WhitespaceSurroundingMachineName.App.Config.Settings.xlsx",
                        "WhitespaceSurroundingMachineName.App.Config.Settings.xlsx"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);

                Assert.IsNotNull(settingsCollection, "settingsCollection should not have been null");
                Assert.AreEqual(1, settingsCollection.MachineConfigurationSettings.Count(), "settingsCollection should contain one item");
                Assert.AreEqual("DevServer", settingsCollection.MachineConfigurationSettings.First().MachineName, "Incorrect machine name");
            }
        }

        /// <summary>
        /// Checks the enforcement of a blank row between the header and the data.
        /// </summary>
        [Test]
        public void LoadSettings009_NoEmptyRowAfterHeaderThrowsException()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (var testFile = Assembly.GetExecutingAssembly().GetEmbeddedResourceFile("SettingsLoader.SampleFiles.NoEmptyRowAfterHeader.App.Config.Settings.xlsx", "NoEmptyRowAfterHeader.App.Config.Settings.xlsx"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };
                Assert.Throws<SpreadsheetHeaderException>(() => loader.LoadSettings(args));
            }
        }

        /// <summary>
        /// Asserts that the NumColumnsToSkip setting works correctly
        /// </summary>
        [Test]
        public void LoadSettings_Preferences_NumColumnsToSkip()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (
                var testFile =
                    Assembly.GetExecutingAssembly().GetEmbeddedResourceFile(
                        "SettingsLoader.SampleFiles.SettingsPreferences-ColSkip.App.Config.Settings.xls",
                        "SettingsPreferences-ColSkip.App.Config.Settings.xls"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);

                Assert.IsNotNull(settingsCollection, "settingsCollection should not have been null");

                Assert.AreEqual(1, settingsCollection.MachineConfigurationSettings.Count(), "settingsCollection should contain one item");
                var settingsRow = settingsCollection.MachineConfigurationSettings.First();
                Assert.AreEqual(1, settingsRow.ConfigurationSettings.Count(), "settingsRow count: incorrect");
                Assert.AreEqual("DevServer_Setting1", settingsRow.ConfigurationSettings[0].Value, "settingsRow value: incorrect");
            }
        }

        /// <summary>
        /// Asserts that the EmptyStringPlaceholder overrides the default behaviour
        /// </summary>
        [Test]
        public void LoadSettings_Preferences_EmptyStringPlaceholder()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (
                var testFile =
                    Assembly.GetExecutingAssembly().GetEmbeddedResourceFile(
                        "SettingsLoader.SampleFiles.SettingsPreferences-EmptyString.App.Config.Settings.xls",
                        "SettingsPreferences-EmptyString.App.Config.Settings.xls"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);

                Assert.IsNotNull(settingsCollection, "settingsCollection should not have been null");

                Assert.AreEqual(1, settingsCollection.MachineConfigurationSettings.Count(), "settingsCollection should contain one item");
                var settingsRow = settingsCollection.MachineConfigurationSettings.First();
                Assert.AreEqual(2, settingsRow.ConfigurationSettings.Count(), "settingsRow count: incorrect");
                Assert.AreEqual("", settingsRow.ConfigurationSettings[0].Value, "settingsRow [0] value: incorrect");
                Assert.AreEqual("[EmptyString]", settingsRow.ConfigurationSettings[1].Value, "settingsRow [1] value: incorrect (should have been verbatim [EmptyString])");
            }
        }

        /// <summary>
        /// Asserts that the NullPlaceholder overrides the default behaviour
        /// </summary>
        [Test]
        public void LoadSettings_Preferences_NullPlaceholder()
        {
            var container = new ConfigGenContainer();
            var loader = container.Resolve<ExcelSettingsLoader>();

            using (
                var testFile =
                    Assembly.GetExecutingAssembly().GetEmbeddedResourceFile(
                        "SettingsLoader.SampleFiles.SettingsPreferences-Null.App.Config.Settings.xls",
                        "SettingsPreferences-Null.App.Config.Settings.xls"))
            {
                var args = new[] { testFile.FullName, "Sheet1" };

                var settingsCollection = loader.LoadSettings(args);

                Assert.IsNotNull(settingsCollection, "settingsCollection should not have been null");

                Assert.AreEqual(1, settingsCollection.MachineConfigurationSettings.Count(), "settingsCollection should contain one item");
                var settingsRow = settingsCollection.MachineConfigurationSettings.First();
                Assert.AreEqual(2, settingsRow.ConfigurationSettings.Count(), "settingsRow count: incorrect");
                Assert.AreEqual("", settingsRow.ConfigurationSettings[0].Value, "settingsRow [0] value: incorrect");
                Assert.AreEqual(null, settingsRow.ConfigurationSettings[1].Value, "settingsRow [1] value: incorrect");
            }
        }
    }
}
